package com.greentreecs.fms.service.impl;

import com.greentreecs.fms.constant.DateConstant;
import com.greentreecs.fms.mapper.QueryIncCurveMapper;
import com.greentreecs.fms.pojo.domain.SingleCurveDO;
import com.greentreecs.fms.pojo.dto.RoomIncCurveDTO;
import com.greentreecs.fms.pojo.param.QueryIncCurveParam;
import com.greentreecs.fms.service.IncomeCurveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.time.LocalDate;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * @author 刀氏春秋
 * @date 2025/6/4
 */
@Service
public class IncomeCurveServiceImpl implements IncomeCurveService {
    @Autowired
    private QueryIncCurveMapper queryIncCurveMapper;

    @Override
    public RoomIncCurveDTO queryRoomIncomeCurveData(QueryIncCurveParam param) throws SQLException {
        List<SingleCurveDO> originCurve = queryIncCurveMapper.queryRoomIncCurveData(param);
        // 依据时间进行排序
        if (originCurve != null)
            Collections.sort(originCurve);
        // 合并日期相同的数据项
        List<SingleCurveDO> mergedCurve = mergeCurveData(originCurve);

        // 结果由日期到数据的映射集合
        RoomIncCurveDTO result = new RoomIncCurveDTO();
        result.setDataDate(new LinkedList<>());
        result.setRealIncome(new LinkedList<>());

        // 可以查询到数据时，从规定的起始日期开始，如果数据项中存在日期，则存入数据，否则存入null空值
        LocalDate traverse = LocalDate.parse(param.getStartDate(), DateConstant.CURVE_DATE_FORMAT);
        LocalDate endDate = LocalDate.parse(param.getEndDate(), DateConstant.CURVE_DATE_FORMAT);
        // 跟随曲线内数据点
        int point = 0;
        while (!traverse.isAfter(endDate)) {
            Double realIncome = null;
            // 判断遍历日期是否与曲线点日期匹配
            // 注意，如果曲线数据没查出来，横轴日期依旧要补充
            if (mergedCurve.size() > point &&
                    mergedCurve.get(point).getDataDate().equals(traverse.format(DateConstant.CURVE_DATE_FORMAT))) {
                // 匹配，写入数据并更新point
                realIncome = mergedCurve.get(point).getPointVal();
                point++;
            }
            // 添加横轴日期
            result.getDataDate().add(traverse.format(DateConstant.CURVE_DATE_FORMAT));
            // 添加收入
            result.getRealIncome().add(realIncome);
            // 日期向后步进
            traverse = traverse.plusDays(1);
        }
        return result;
    }

    private List<SingleCurveDO> mergeCurveData(List<SingleCurveDO> sorted) {
        List<SingleCurveDO> merged = new LinkedList<>();
        // 遍历已按时间排序的收入数据，如果当前merged顶部数据时间和sorted当前时间相同，则pointVal合并
        if (sorted != null && sorted.size() > 0) {
            // 如果至少有一个元素在sorted内，则将其置入merged列表中
            merged.add(sorted.get(0));
            String topDate = merged.get(0).getDataDate();
            for (SingleCurveDO record : sorted) {
                if (topDate.equals(record.getDataDate())) {
                    // 日期相同，意味着合并顶部数据
                    merged.get(merged.size() - 1).plusVal(record.getPointVal());
                } else {
                    // 日期不同，意味着将数据项置入顶部
                    merged.add(record);
                }
            }
        }
        return merged;
    }
}
